/**
 **oj/term - A terminal interface
 *
 * The term module provides a command-line interface for interacting with the
 * system.
 *
 */

define(['oj/os'], function(os) {
    
    
    window.term = {}
    
    
    term.Term = function(container) {
        /**
         ** Term - Term object
         *
         */
        
        var self = {}
        
        
        var COMMANDS = {
             
            'cd': {
                'help': "cd 'path'      - Change the current working directory",
                'do': function (args) {
                    self.print_style = 'term_files'
                    os.chdir(args[1], self.response)
                    self.setprompt( '' )
                }
            },
            
            'cp': {
                'help': "cp 'src' 'dst' - Copy a file",
                'do': function (args) {
                    args.shift()
                    args[0] = os.path.abspath(args[0])
                    args[1] = os.path.abspath(args[1])
                    print('['+args+']')
                    os.concat( args, false, self.response)
                    self.setprompt('')
                }
            },
            
            'help': {
                'help': "help           - List available commands",
                'do': function (args) {
                    Object.keys(COMMANDS).forEach(function (cmd) {
                        self.print(COMMANDS[cmd]['help'])
                    })
                    self.response()
                }
            },
            
            'id': {
                'help': "id             - Get user identity",
                'do': function (args) {
                    self.print(os.environ.user.name)
                    self.response()
                }
            },
            
            'logout': {
                'help': "logout         - Log current user out",
                'do': function (args) {
                    os.logout(document.location, function(m) {
                        document.location = m.logout
                    });
                }
            },
            
            'ls': {
                'help': "ls ['path']    - List files",
                'do': function (args) {
                    var dir = '-'
                    
                    args.shift()
                    
                    while (dir.charAt(0) === '-' && args.length > 0)
                        dir = args.shift()
                    
                    if (dir.charAt(0) === '-')
                        dir = '.'
                    
                    self.print_style = 'term_files'
                    os.listdir(dir, self.response)
                    self.setprompt('')
                }
            },
            
            'mkdir': {
                'help': "mkdir 'path'   - Make a directory",
                'do': function (args) {
                    os.mkdir( args[ 1 ], self.response )
                    self.setprompt('')
                }
            },
            
            'mv': {
                'help': "mv 'src' 'dst' - Move file or directory",
                'do': function (args) {
                    os.move(args[1], args[2], self.response)
                    self.setprompt('')
                }
            },
            
            'echo': {
                'help': "echo          - Send to the terminal",
                'do': function (args) {
                    self.print(args[1])
                    self.response()
                }
            },
            
            'rm': {
                'help': "rm 'path'      - Remove file",
                'do': function (args) {
                    os.remove(args[1], self.response)
                    self.setprompt('')
                }
            },
            
            'rmdir': {
                'help': "rmdir 'path'   - Remove directory",
                'do': function (args) {
                    os.rmdir(args[1], self.response)
                    self.setprompt('')
                }
            },
            
            'time': {
                'help': "time           - Get current local time",
                'do': function (args) {
                    self.print((new Date()).toLocaleString())
                    self.response()
                }
            },
            
            'version': {
                'help': "version        - Get oj version",
                'do': function (args) {
                    self.print('oj ' + oj.version)
                    self.response()
                }
            }
        }
        
        
        self.print = function (output) {
            /**
             *>print(output)
             *
             * Writes output to the history buffer.
             *
             */
            
            if (self.buffer.length === os.environ.term_history)
                self.history.removeChild(self.buffer.shift())
            
            if (!(output instanceof HTMLElement)) {
                if (typeof output === 'undefined') {
                    output = '';
                } else if (typeof output === 'object') {
                    if (output.hasOwnProperty('error'))
                        self.print_style = 'term_error'
                    output = JSON.stringify(output)
                }
                output = output.replace(/", "|","|"]|"}/g, '\n')
                output = output.replace(/\["|{"|\[\]/g, '')
                output = output.replace(/":"|": "/g, ': ')
                output = output.replace(/\\\//g, '/')
            }
            
            output = oj.element(self.history, 'div', 'term_print ' + self.print_style, [output])
            self.buffer.push(output)
            self.cmd.scrollIntoView()
            
            return output
        }
        
        
        self.read = function (prompt, fn) {
            /**
             *>read('prompt', callback)
             *
             * Read input from the user.
             *
             */
            
            self.setprompt(prompt)
            self.cmd.focus()
            self.callback = fn
            
            return self
        }
        
        
        self.setprompt = function (prompt) {
            /**
             *>setprompt('prompt')
             *
             * Updates the prompt component value.
             *
             */
            
            for (var prop in os.environ)
                prompt = prompt.replace('$'+prop, os.environ[prop])
            
            self.prm.textContent = prompt
            os.environ.prompt = prompt
            self.layout()
            
            return self
        }
        
        
        self.response = function (response) {
            /**
             *>response(response)
             *
             * Prints the response and prompts for input.
             *
             */

            self.print(response)
            self.read('$cwd#', self.execute)
        }
        
        
        self.execute = function (input) {
            /**
             *>execute('input')
             *
             * Executes a pipe separated string of commands.
             *
             */
            
            var cmd = input.split(' ')
    
            self.print_style = ''
            
            if (cmd[0] in COMMANDS)
                COMMANDS[cmd[0]]['do'](cmd)
            else {
                window.open((cmd.length > 1) ? '/' + cmd[0] + '?f=' + os.path.abspath(cmd[1]) : '/' + cmd[0])
                self.response()
            }
            
            return self
        }
        
        
        self.layout = function () {
            /**
             *>layout()
             *
             * Updates the layout of the display.
             *
             */
            
            self.cmd.style.width = (self.panel.offsetWidth - self.prm.offsetWidth - 30) + 'px'
            
            return self
        }
        
        
            
        self.container = container
            
        self.container.style['background-color'] = '#111111'
            
        self.buffer   = []
        self.callback = undefined
        self.panel    = oj.element(self.container, 'div', 'term_container')
        self.history  = oj.element(self.panel, 'div', 'term_history')
        self.prm      = oj.element(self.panel, 'span', 'term_prompt')
            
        self.print_style            = ''
        self.prm.style.paddingRight = '2px'
            
        self.cmd         = oj.element(self.panel, 'input', 'term_cmdline', {'type': 'text'})
        self.cmd.onfocus = function() {self.cmd.style.outline='none'}
            
        self.panel.onresize = self.layout
        self.panel.onclick  = self.focus
            
        document.onclick = self.focus
            
        self.cmd.onkeypress = function(event) {
            if (event.keyCode != '13') return true
                
            var p = self.prm.cloneNode(true),
                input = self.cmd.value
            
            p.style.marginRight = '1px'
            self.cmd.value = ''
            
            self.print(oj.element('span', '', [ p,
                oj.element('span', 'term_cmdline', [input])
            ]))
                
            if (input.length > 0 && self.callback) {
                var fn = self.callback
                self.callback = undefined
                fn(input)
            }
        }
            
        os.environ.term_history = 100
        
        return self
    }
    
    
    oj.element(document.head, 'style', {'type': 'text/css'}, [
        '.term_container {',
        '  color: #cccccc;',
        '  border: 0;',
        '  margin: 0;',
        '  padding: 5px;',
        '  font: normal normal normal 16pt monospace;',
        '  white-space: pre;',
        '}',
        '.term_history {',
        '}',
        '.term_prompt {',
        '  color: white;',
        '}',
        '.term_cmdline {',
        '  color: #cccccc;',
        '  background: none;',
        '  font: normal normal normal 16pt monospace;',
        '  white-space: pre;',
        '  border: 0;',
        '}',
        '.term_print {',
        '  padding-top: 3px;',
        '}',
        '.term_files {',
        '  color: #00ff00;',
        '}',
        '.term_error {',
        '  color: #ff0000;',
        '}'
    ])
    
    
    if (oj.main === 'oj/term') {
        /**
         **oj.main
         *
         * When run as the main application this module will automatically
         * create a Term instance using document.body as the container.
         *
         * Available commands
         *
         *./# help
         *.cd 'path'      - Change the current working directory
         *.cp 'src' 'dst' - Copy a file
         *.help           - List available commands
         *.id             - Get user identity
         *.logout         - Log current user out
         *.ls ['path']    - List files
         *.mkdir 'path'   - Make a directory
         *.mv 'src' 'dst' - Move file or directory
         *.echo           - Send to the terminal
         *.rm 'path'      - Remove file
         *.rmdir 'path'   - Remove directory
         *.time           - Get current local time
         *.version        - Get oj version 
         *
         */
        
        os.identity(document.location, function(m) {
            if (m.hasOwnProperty('login')) {
                document.location = m.login
                return
            }
            
            os.environ.user = m
            
            var sh = term.Term(document.body)
            
            sh.print('Welcome ' + os.environ.user.name)
            sh.print((new Date()).toLocaleString())
            sh.print(oj.version)
            sh.print()
            sh.print("Type 'help' for a list of commands.")
            sh.print()
            sh.read('$cwd#', sh.execute)
        })
        
        oj.element(document.head, 'syle', {'type': 'text/css'}, [
            'html {',
            '  height: 100%;',
            '}',
            'body {',
            '  height: 100%;',
            '}'
        ])
    }
    
    return term
    
})
